﻿using NLog;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace CSharpAllDemo.Serial
{
    public class TcpServerManager
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();


        // 私有静态实例
        private static readonly TcpServerManager _instance = new TcpServerManager();
        // 公共静态方法，返回实例
        public static TcpServerManager Instance => _instance;

        private bool IsListened = false;

        private Socket mServerSocket;

        private List<Thread> mClientSocketThreadList = new();
        private List<string> mClientIpPortList = new();
        private List<Socket> mClientSocketList = new();


        // 私有构造函数，防止外部实例化
        private TcpServerManager()
        {

        }

        public void Init(int port)
        {

            // 创建一个新的 Socket 对象，指定为 IPv4、面向流的（TCP）协议
            mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //允许套接字复用
            mServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            // 服务器绑定指定终端（IP,Port）
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);//创建终端
            mServerSocket.Bind(localEndPoint);   //绑定终端

            mServerSocket.Listen(10);
            //创建并使用线程侦听
            Thread listenThread = new Thread(OnListenClient);
            listenThread.IsBackground = true;
            listenThread.Start();
            IsListened = true;

            // 创建一个 Timer 实例
            Timer timer = new Timer(state =>
            {
                // 这里是定时任务的代码




            },
            null,                    // 传递给回调方法的状态对象（这里我们传递 null）
            TimeSpan.Zero,           // 初次延迟时间
            TimeSpan.FromSeconds(1) // 定时器间隔时间
            );




        }
        /// <summary>
        /// 侦听客户端
        /// </summary>
        public void OnListenClient()
        {

            while (true)
            {
                //接受一个客户端的连接请求
                Socket socket = mServerSocket.Accept();
                System.Diagnostics.Debug.WriteLine("==有客户端连接==");
                //创建接收数据线程
                Thread thread = new Thread(OnReceived);
                thread.Name = (mClientSocketThreadList.Count + 1) + "";
                thread.IsBackground = true;
                thread.Start(socket);

                //添加对象到集合
                mClientIpPortList.Add(socket.RemoteEndPoint.ToString());  //添加远程终端到集合
                mClientSocketList.Add(socket);                                   //添加Socket对现象到集合
                mClientSocketThreadList.Add(thread);                             //创建对应的客户端Socket线程对象并添加到集合
            }
        }

        /// <summary>
        /// 接收数据方法
        /// </summary>
        public void OnReceived(object socketClientPara)
        {
            Socket socket = socketClientPara as Socket;
            string remoteEndPoint = socket.RemoteEndPoint.ToString();
            System.Diagnostics.Debug.WriteLine("==remoteEndPoint==" + remoteEndPoint);

            while (true)
            {
                try
                {
                    // 读取客户端发送的数据
                    byte[] buffer = new byte[1024 * 1024];
                    if (socket == null || !socket.Connected)
                    {
                        break;
                    }
                    // 接收客户端发来的数据
                    int dataLength = socket.Receive(buffer);
                    if (dataLength > 0)
                    {
                        // 将接收的数据转换为字符串并输出
                        string dataReceived = Encoding.ASCII.GetString(buffer, 0, dataLength);
                        System.Diagnostics.Debug.WriteLine("==接受到的数据==" + dataReceived);

                    }

                }
                catch (Exception ex)
                {
                }
            }
        }

        public void Send(string ipPort, string data)
        {
            if (IsListened)
            {
                string socketIpPort = mClientIpPortList.Find(s => s.Equals(ipPort));
                Socket socket = mClientSocketList.Find(s => s.RemoteEndPoint.ToString().Equals(ipPort));
                if (socket != null)
                {
                    NetworkStream Stream = new NetworkStream(socket);
                    string dataToSend = data;
                    byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend);
                    Stream.Write(dataBytes, 0, dataBytes.Length);
                }
            }
        }


    }
}
